package com.aurora.neo4j.service.imp;

import cn.hutool.extra.pinyin.PinyinUtil;
import com.alibaba.fastjson.JSON;
import com.aurora.neo4j.dao.PersonRepository;
import com.aurora.neo4j.entity.Lines;
import com.aurora.neo4j.entity.Nodes;
import com.aurora.neo4j.entity.RelationVo;
import com.aurora.neo4j.relation.BaseRelationShip;
import com.aurora.neo4j.result.PersonOneDepthRelationVo;
import com.aurora.neo4j.service.PersonService;
import com.aurora.service.RedisService;
import com.aurora.spider.houyuantuan.HitProject;
import com.aurora.spider.houyuantuan.Person;
import com.aurora.spider.houyuantuan.PersonShip;
import com.aurora.spider.utils.SpiderUtil;
import com.aurora.star.dto.StarQueryDto;
import com.geccocrawler.gecco.spider.HrefBean;
import com.google.common.collect.Maps;
import lombok.extern.log4j.Log4j2;
import org.neo4j.driver.internal.InternalPath;
import org.neo4j.driver.types.Node;
import org.neo4j.driver.types.Relationship;
import org.neo4j.ogm.model.Result;
import org.neo4j.ogm.session.Session;
import org.neo4j.ogm.session.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * @program: blog-aurora
 * @description: 人物操作
 * @author: jonk
 * @create: 2023-08-31 13:33
 **/
@Log4j2
@Service("personService")
public class PersonServiceImpl implements PersonService {
    @Resource
    PersonRepository personRepository;

    @Resource
    private SessionFactory sessionFactory;

    @Override
    public RelationVo findStarByName(String name, int limit) {
        Result result = personRepository.findStarByName(name, limit);
        return getListResultNew(result);
    }

    @Override
    public Result queryByCypher(String cql) {
        Session session = sessionFactory.openSession();
        Result result = session.query(cql, Maps.newHashMap());
        return result;
    }

    @Override
    public RelationVo findStarByName(StarQueryDto dto) {
        Result result = personRepository.findStarByName(dto.getName(), dto.getLimit());
        return getListResultNew(result);
    }

    @Override
    public List<PersonOneDepthRelationVo> findStarOneDepthByName(StarQueryDto dto) {
        List<PersonOneDepthRelationVo> starOneDepthByName = personRepository.findStarOneDepthByName(dto.getName());
        return starOneDepthByName;
    }

    @Autowired
    RedisService redisService;

    @Override
    public void personShipEvent(PersonShip personShip) {

        for (HitProject hitProject : personShip.getRelaList()) {
            //自己
            if (hitProject.getRelation() == null) {
                continue;
            }
            String fName = hitProject.getPersonName() == null ? hitProject.getSpName() : hitProject.getPersonName();
            //关联两个人的关系
            Long parentId = personShip.getStarId();
            if (parentId != null && parentId > 0) {
                BaseRelationShip ship = new BaseRelationShip();
                ship.setParentId(parentId);
                ship.setSonImgUrl(hitProject.getImgUrl()==null?hitProject.getImgUrl2():hitProject.getImgUrl());
                List<HrefBean> hrefBeans = hitProject.getUrls();
                if (hrefBeans != null && hrefBeans.size() > 0) {
                    addurls(hitProject, fName, ship, hrefBeans);
                } else {
                    addnames(hitProject, ship);
                }
            }
        }
    }

    @Override
    public void saveOrUpdate(Person person) {
        saveOrUpdateNeo4j(person,"saveOrUpdate");
    }

    private void addnames(HitProject hitProject, BaseRelationShip ship) {
        try {
            String relateionpy2 = PinyinUtil.getPinyin(hitProject.getRelation2(), "");
            ship.setRelation(relateionpy2);
            ship.setRelationName(hitProject.getRelation2());
            //更新或者添加朋友person
            ship.setSonName(hitProject.getSpName());
            Person person= new Person();
            person.setName(ship.getSonName());
            person.setImgUrl(ship.getSonImgUrl());
            saveOrUpdateNeo4j(person, "simpleAddByName");
            createPersonRelationByName(ship);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void addurls(HitProject hitProject, String fName, BaseRelationShip ship, List<HrefBean> hrefBeans) {
        try {
            ship.setSonName(fName);
            //关系转拼音
            String relateionpy = PinyinUtil.getPinyin(hitProject.getRelation(), "");
            ship.setRelationName(hitProject.getRelation());
            ship.setRelation(relateionpy);
            String url = hrefBeans.get(0).getUrl();
            ship.setSonId(SpiderUtil.getUrlId(url));
            Person person= new Person();
            person.setName(ship.getSonName());
            person.setImgUrl(ship.getSonImgUrl());
            person.setId(ship.getSonId());
            saveOrUpdateNeo4j(person, "simpleAddById");
            createPersonRelation(ship);
        } catch (Exception e) {
         log.error("addurls err {}",e);
        }
    }

    private synchronized void saveOrUpdateNeo4j(Person person, String type) {
        Map parseObject = JSON.parseObject(JSON.toJSONString(person), Map.class);
        if (type.equals("simpleAddById")) {
            personRepository.simpleAddById(parseObject);
        } else if(type.equals("simpleAddByName")) {
            personRepository.simpleAddByName(parseObject);
        } else{
            personRepository.saveOrUpdate(parseObject);
        }
    }

    private void createPersonRelationByName(BaseRelationShip ship) {
        try {
            String cql = "OPTIONAL MATCH  (s:Person{id:" + ship.getParentId() + "}),(e:Person{name:'" + ship.getSonName() + "'})" +
                    "MERGE (s)-[:" + ship.getRelation() + " {name:'" + ship.getRelationName() + "'}]->(e)";
            this.queryByCypher(cql);
        } catch (Exception e) {
            log.error("createPersonRelationByName err {}",e);
        }
    }

    private void createPersonRelation(BaseRelationShip ship) {
        try {
            String cql = "OPTIONAL MATCH  (s:Person{id: " + ship.getParentId() + "}),(e:Person{id:" + ship.getSonId() + "})" +
                    "MERGE (s)-[:" + ship.getRelation() + " {name:'" + ship.getRelationName() + "'}]->(e)";
            this.queryByCypher(cql);
        } catch (Exception e) {
            log.error("createPersonRelation err {}",e);
        }
    }


    private RelationVo getListResultNew(Result result) {
        RelationVo relationVo = new RelationVo();
        Set<Lines> LineList = new HashSet<>();
        Set<Nodes> nodeSet = new HashSet<>();
        Long rootId = null;
        Iterable<Map<String, Object>> maps = result.queryResults();
        Iterator<Map<String, Object>> iterator = maps.iterator();
        while (iterator.hasNext()) {
            Map<String, Object> map = iterator.next();
            // 获取中心节点
            InternalPath.SelfContainedSegment[] root = (InternalPath.SelfContainedSegment[]) map.get("p");
            for (InternalPath.SelfContainedSegment selfContainedSegment : root) {
                Node start = selfContainedSegment.start();
                if (rootId == null) {
                    rootId = start.id();
                }
                Nodes myNode = new Nodes();
                myNode.setId(start.id() + "");
                myNode.setText(start.get("name").asString());
                String imgUrl = start.get("imgUrl").asString();
                String html = "<div class=\"c-my-node\" style=\"background-image: url(" + imgUrl + ");border:#ff875e solid 3px;\"><div class=\"c-node-name\" style=\"color:#ff875e\">" + start.get("name").asString() + "</div></div>";
                myNode.setInnerHTML(html);
                nodeSet.add(myNode);
                //<div class='c-my-node' style='background-image: url(https://dss0.baidu.com/6ONWsjip0QIZ8tyhnq/it/u=2677153550,2207805387&fm=58&app=83&f=JPEG?w=250&h=250&s=249039DDC2D153D411A851360300C062);border:#ff875e solid 3px;'><div class='c-node-name' style='color:#ff875e'>李达康</div></div>
                Node end = selfContainedSegment.end();
                Nodes myNode2 = new Nodes();
                myNode2.setId(end.id() + "");
                String name2 = end.get("name").asString();
                myNode2.setText(name2);

                String imgUrl2 = end.get("imgUrl").asString();
                String html2 = "<div class=\"c-my-node\" style=\"background-image: url(" + imgUrl2 + ");border:#ff875e solid 3px;\"><div class=\"c-node-name\" style=\"color:#ff875e\">" + name2 + "</div></div>";
                myNode2.setInnerHTML(html2);
                nodeSet.add(myNode2);
                Relationship relationship = selfContainedSegment.relationship();
                Lines lines = new Lines();
                lines.setFrom(relationship.startNodeId() + "");
                lines.setTo(relationship.endNodeId() + "");
                lines.setColor("#d2c0a5");
                lines.setFontColor("#d2c0a5");
                String name = relationship.get("name").asString();
                lines.setText(name);//关系
                LineList.add(lines);
            }
            relationVo.setLines(LineList);
            relationVo.setRootId(rootId + "");
            relationVo.setNodes(nodeSet);
        }
        return relationVo;
    }
}